import http from '@ohos.net.http';
import router from '@ohos.router';
import promptAction from '@ohos.promptAction';
import { Auth } from './Auth';
import { Logger } from './Logger';

const BASE_URL = 'https://api-harmony-teach.itheima.net/hm/'

const req = http.createHttp()

const request = <T = unknown>(
  url: string,
  method: http.RequestMethod = http.RequestMethod.GET,
  params: Object = {}
) => {
  let fullUrl = BASE_URL + url
  const options: http.HttpRequestOptions = {
    header: {
      'Content-Type': 'application/json',
    },
    readTimeout: 30000,
    method,
  }

  //如果是对象数据拼接URL，如果是其他则携带在 extraData
  if (method === http.RequestMethod.GET) {
    const urlParams = Object.keys(params).map(key => `${key}=${params[key]}`)
    fullUrl += `?${urlParams.join('&')}`
  } else {
    options.extraData = params
  }

  const user = Auth.getUser()
  if (user.token) {
    options.header['Authorization'] = `Bearer ${ user.token}`
  }

  Logger.info(`REQUEST->${url}->${method}`, JSON.stringify(params))
  return req.request(fullUrl, options)
    .then(res => {
      //成功
      if (res.result) {
        Logger.info(`RESPONSE->${url}->${method}`, res.result.toString().substring(0, 250))
        const result = JSON.parse(res.result as string) as {
          code: number
          message: string
          data: T
        }
        if (result.code === 10000) {
          return result
        }

        //登录失效
        if (result.code === 401) {
          Auth.delUser()
          router.pushUrl({
            url: ''
          }, router.RouterMode.Single)
        }

      }

      //没有响应数据认为失败，业务状态码错误也失败
      return Promise.reject(res.result)
    })
    .catch(e => {
      Logger.info(`RESPONSE->${url}->${method}`, JSON.stringify(e).substring(0, 250))
      promptAction.showToast({message:'网络错误'})
      //失败
      return Promise.reject(e)
    })
    .finally(()=>{
      //释放请求资源
      req.destroy()
    })
}

export class Request {
  static get<T>(url: string, params?: object) {
    return request<T>(url, http.RequestMethod.GET, params)
  }

  static post<T>(url: string, params?: object) {
    return request<T>(url, http.RequestMethod.POST, params)
  }

  static put<T>(url: string, params?: object) {
    return request<T>(url, http.RequestMethod.PUT, params)
  }

  static delete<T>(url: string, params?: object) {
    return request<T>(url, http.RequestMethod.DELETE, params)
  }
}